package com.ai.dmc.utils.config;

import java.io.File;
import java.io.FileInputStream;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.ai.dmc.utils.string.StringUtil;

/**
 * <p>
 * Title: Configure.java
 * </p>
 * <p>
 * Description:初始化参数工具类，从.properties配置文件中取得数据信息 ，使用前请设置配置文件路径，如： String
 * confFilePath =
 * arg0.getServletContext().getRealPath("/WEB-INF/conf/asiainfo.properties");
 * Configure.getInstance().setConfFileName(confFilePath);<br/>
 * 在使用多个配置文件时，需要增加配置类型来区别各个配置文件（这里增加配置类型是为了防止不同配置文件中有相同的参数配置），<br/>
 * 可以使用Configure.getInstance().addConfFileName(String configType, String
 * fileName)方法来添加配置文件。
 * </p>
 * <p>
 * Copyright: Copyright (c) 2002
 * </p>
 * <p>
 * Company: Asia Info
 * </p>
 * 
 * ********** 新增加对多个配置文件的支持
 * 
 * 
 */
public class Configure {
	
	public static final String URL_PATH = "URL_PATH";

	private static Log log = LogFactory.getLog(Configure.class);

	private static Configure configure = new Configure();

	private static final String DEFAULT_CONFIG_TYPE = "ASIAINFO_PROPERTIES";// 默认的配置类型，支持旧的asiainfo.properties配置

	
	// 记录每个文件类型对应的文件的修改时间
	private static Map<String, Long> modifiedTimeMap = new HashMap<String, Long>();

	// 记录configType对应的文件路径
	private static Map<String, String> fileNameMap = new HashMap<String, String>();

	// 记录文件的绝对路径
	private static Map<String, String> absPathMap = new HashMap<String, String>();

	// 记录configType对应的配置信息
	private static Map<String, Properties> configMap = new HashMap<String, Properties>();

	/**
	 * 默认构造函数，使用默认的文件名称
	 * 
	 * @throws Exception
	 */
	private Configure() {
	}

	/**
	 * 获取单一实例
	 * 
	 * @return Configure
	 * 
	 */
	public static Configure getInstance() {
		return configure;
	}

	/**
	 * 对默认配置文件的设置，适用于一个properites配置文件的情况， 在Listener中调用这个方法设置默认的配置。
	 * 
	 * @param fileName
	 *            void
	 * @throws Exception
	 * @deprecated 为了兼容以前的版本。现在建议使用addConfFileName方法，设置configType
	 * 
	 */
	public void setConfFileName(String fileName) throws Exception {
		// 初始化
		initProperties(DEFAULT_CONFIG_TYPE, fileName);
	}

	/**
	 * 在Listener中设置配置文件的路径及名称，调用这个方法可添加一个或多个配置文件。
	 * 配置文件类型可自行定义，不要使用ASIAINFO_PROPERTIES，
	 * 
	 * @param configType
	 *            配置文件类型，可根据各个应用自己定义，不要使用ASIAINFO_PROPERTIES
	 * @param fileName
	 *            文件路名称（包含路径）
	 * 
	 *            void
	 * @throws Exception
	 * 
	 */
	public void addConfFileName(String configType, String fileName)
			throws Exception {
		initProperties(configType, fileName);
	}

	/**
	 * 取得默认配置文件的特定参数
	 * 
	 * @param strKey
	 *            参数关键字
	 * 
	 * @return String 配置参数值
	 * @throws Exception
	 */
	public String getProperty(String strKey) {
		try {
			return getProperty(DEFAULT_CONFIG_TYPE, strKey);
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * 
	 * 通过指定的配置类型取得参数值
	 * 
	 * @param configType
	 *            设置的配置类型
	 * @param strKey
	 *            参数的key
	 * @return String 参数的value
	 * @throws Exception
	 * 
	 * 
	 */
	public String getProperty(String configType, String strKey)
			throws Exception {
		// 配置类型为空，则抛出异常
		if (StringUtil.isEmpty(configType)) {
			throw new Exception("----Configure--err-------:configType is null");
		}
		try {
			// 未加载
			if (configMap.get(configType) == null) {
				throw new Exception("----Configure--err-------:configType["
						+ configType + "]is not initialized");
			}
			File fileObj = new File(fileNameMap.get(configType));
			// 先判断文件是否被修改，被修改则需要重新初始化
			if (fileObj.lastModified() > modifiedTimeMap.get(configType)) {
				initProperties(configType, fileNameMap.get(configType));
			}
			// 取得配置信息
			Properties properties = configMap.get(configType);
			return StringUtil.obj2Str(properties.getProperty(strKey));
		} catch (Exception excep) {
			excep.printStackTrace();
			return "";
		}
	}

	
	/**
	 * 获取组件或应用的部署url 
	 * @param key   core.properties配置的属性名称
	 * @return      组件或应用的web url
	 * @throws Exception 
	 */
	public String getWebUrl(String key) throws Exception{
		return this.getProperty(this.URL_PATH, key) ;
	}
	
	/**
	 * 
	 * @return
	 */
	public Map<String,String> getWebUrlMap(){
		Map map = new HashMap<String,String>();
		Properties props = configMap.get(this.URL_PATH);
		Enumeration enums = props.propertyNames(); 
		String name = null ;
		while(enums.hasMoreElements()){
			name = (String) enums.nextElement() ;
			map.put(name, props.getProperty(name,""));
		}
		return map ;
	}
	
	
	/**
	 * 
	 * 为某个配置类型初始化配置信息
	 * 
	 * @param configType
	 *            配置类型
	 * @param fileName
	 *            配置文件名（包含路径） void
	 * @throws Exception
	 * 
	 */
	synchronized private boolean initProperties(String configType,
			String fileName) throws Exception {
		// 如果没有设置配置类型，则抛出异常
		if (StringUtil.isEmpty(configType)) {
			throw new Exception("----Configure--err-------:configType is null");
		}
		if (StringUtil.isEmpty(fileName)) {
			throw new Exception("----Configure--err-------:fileName is null");
		}
		Properties props = new Properties();
		File fileObj = new File(fileName);
		String absPathStr = fileObj.getAbsolutePath();
		log.debug("fileName:" + fileName + "\r\n Absolute Path:" + absPathStr);
		if (!fileObj.exists()) {
			throw new Exception("parameter file not found:" + fileName + "\r\nAbsolute Path:"
					+ absPathStr);
		}
		FileInputStream fis = new FileInputStream(fileName);
		props.load(fis);
		fis.close();
		// 记录配置文件信息
		modifiedTimeMap.put(configType, fileObj.lastModified());
		fileNameMap.put(configType, fileName);
		absPathMap.put(configType, absPathStr);
		configMap.put(configType, props);
		return true;
	}

	/**
	 * 取得默认配置文件的绝对路径
	 * 
	 * @return String
	 * 
	 */
	public String getAbsPath() {
		return getAbsPath(DEFAULT_CONFIG_TYPE);
	}

	/**
	 * 取得指定配置类型的配置文件的绝对路径
	 * 
	 * @return String
	 * 
	 */
	public String getAbsPath(String configType) {
		return absPathMap.get(configType);
	}
	
	public Properties getPropFile(String configType){
	    Properties properties = configMap.get(configType);
	    return properties;
	}
}